﻿using System;
using Common;
using UnityEngine;
using Object = UnityEngine.Object;

namespace GameCamera
{
    public interface ICameraController
    {
        void OnEnter(Camera camera);
        void OnExit();
        void FixedUpdate();
    }
    
    public class DummyCameraController : ICameraController
    {
        public void OnEnter(Camera _)
        {
        }

        public void OnExit()
        {
        }

        public void FixedUpdate()
        {
        }
    }
    
    public class CameraManager : Singleton<CameraManager>
    {
        private Camera m_MainCamera;
        public Camera mainCamera => m_MainCamera;
        
        private ICameraController m_CameraController;

        #region Camera Controllers

        private readonly DummyCameraController m_DummyCameraController = new DummyCameraController();
        private readonly FollowCameraController m_FollowCameraController = new FollowCameraController();
        

        #endregion
        
        public void Init()
        {
            var go = new GameObject("MainCamera");
            m_MainCamera = go.AddComponent<Camera>();
            m_MainCamera.backgroundColor = Color.gray;
            Object.DontDestroyOnLoad(go);
            
            SwitchCameraController(m_DummyCameraController);
            SetMainCameraEnable(true);
        }
        
        public void SetMainCameraEnable(bool enable)
        {
            if (m_MainCamera != null) m_MainCamera.enabled = enable;
            if (enable)
            {
                m_CameraController?.FixedUpdate();
            }
        }
        
        private void SwitchCameraController(ICameraController controller)
        {
            m_CameraController?.OnExit();
            m_CameraController = controller;
            m_CameraController?.OnEnter(m_MainCamera);
        }
        
        public void SetFollowTarget(Transform followTarget, Transform lookAtTarget = null, FollowStrategy followStrategy = null)
        {
            m_FollowCameraController.Follow(followTarget);
            m_FollowCameraController.LookAt(lookAtTarget);
            
            if (m_CameraController != m_FollowCameraController)
            {
                SwitchCameraController(m_FollowCameraController);
            }

            if (followStrategy != null)
            {
                m_FollowCameraController.SwitchFollowStrategy(followStrategy);
            }
        }
        
        
        public void FixedUpdate()
        {
            try
            {
                if (!m_MainCamera.isActiveAndEnabled) return;
                m_CameraController?.FixedUpdate();
            }
            catch (Exception e)
            {
#if UNITY_EDITOR
                Debug.LogException(e);
#endif
            }

        }
    }
}